﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.IO;
using biolit_config;
using System.Xml.XPath;
using System.Windows;

namespace UCSD_BioLit
{
    internal class BootStrap
    {
        private string AppDataDir;
        XPathNavigator _navigator;
        XPathDocument _docNavigator;
        XPathNodeIterator _nodeIterator;
        internal BootStrap()
        {
            AppDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Biolit_TechPreview_Dec_2009");
        }


        public void BootStrapSequence()
        {
            BootStrapAppDirStructure();
            BootStrapAppSettingsFile();
            BootStrapXSDFile();
        }

        private void BootStrapAppDirStructure()
        {

            CreateDirIFNotPresent(AppDataDir);
            CreateDirIFNotPresent(Path.Combine(AppDataDir, @"Ontologies"));
        }

        private void CreateDirIFNotPresent(string Dir)
        {
            if (false == Directory.Exists(Dir))
            {
                Directory.CreateDirectory(Dir);
            }
        }

        private void BootStrapXSDFile()
        {
            string FileName = Path.Combine(AppDataDir, @"biolit_schema.xsd");
            string OntologyMarkup = Path.Combine(AppDataDir, @"ontology_schema.xsd");
            string DBMarkup = Path.Combine(AppDataDir, @"db_schema.xsd");
            if (false == File.Exists(FileName))
            {
                using (StreamWriter sw = new StreamWriter(FileName))
                {
                    sw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
                    sw.WriteLine("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://biolit.ucsd.edu/biolitschema\" xmlns=\"http://biolit.ucsd.edu/biolitschema\">");
                    sw.WriteLine("<xs:element name=\"biolit-term\">");
                    sw.WriteLine("<xs:complexType>");
                    sw.WriteLine("<xs:simpleContent>");
                    sw.WriteLine("<xs:extension base=\"xs:string\">");
                    sw.WriteLine("<xs:attribute name=\"type\" type=\"xs:string\" use=\"required\"/>");
                    sw.WriteLine("<xs:attribute name=\"id\" type=\"xs:string\"  use=\"required\"/>");
                    sw.WriteLine("<xs:attribute name=\"status\" type=\"xs:string\"/>");
                    sw.WriteLine("<xs:attribute name=\"OntName\" type=\"xs:string\"/>");
                    sw.WriteLine("<xs:attribute name=\"url\" type=\"xs:string\"/>");
                    sw.WriteLine("</xs:extension>");
                    sw.WriteLine("</xs:simpleContent>");
                    sw.WriteLine("</xs:complexType>");
                    sw.WriteLine("</xs:element>");
                    sw.WriteLine("</xs:schema>");
                }


            }
            if (false == File.Exists(OntologyMarkup))
            {
                using (StreamWriter ontWriter = new StreamWriter(OntologyMarkup))
                {
                    ontWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
                    ontWriter.WriteLine("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\" targetNamespace=\"http://biolit.ucsd.edu/biolitschema1\">");
                    ontWriter.WriteLine("<xs:element name=\"named-content\" nillable=\"true\">");
                    ontWriter.WriteLine("<xs:complexType>");
                    ontWriter.WriteLine("<xs:simpleContent msdata:ColumnName=\"named-content_Text\" msdata:Ordinal=\"2\">");
                    ontWriter.WriteLine("<xs:extension base=\"xs:string\">");
                    ontWriter.WriteLine("<xs:attribute name=\"content-type\" type=\"xs:string\" />");
                    ontWriter.WriteLine("<xs:attribute name=\"id\" type=\"xs:string\" />");
                    ontWriter.WriteLine("</xs:extension>");
                    ontWriter.WriteLine("</xs:simpleContent>");
                    ontWriter.WriteLine("</xs:complexType>");
                    ontWriter.WriteLine("</xs:element>");
                    ontWriter.WriteLine("</xs:schema>");
                }
            }


            if (false == File.Exists(DBMarkup))
            {
                using (StreamWriter dbWriter = new StreamWriter(DBMarkup))
                {
                    dbWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
                    dbWriter.WriteLine("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\" targetNamespace=\"http://biolit.ucsd.edu/biolitschema2\">");
                    dbWriter.WriteLine("<xs:element name=\"ext-link\" nillable=\"true\">");
                    dbWriter.WriteLine("<xs:complexType>");
                    dbWriter.WriteLine("<xs:simpleContent msdata:ColumnName=\"ext-link_Text\" msdata:Ordinal=\"2\">");
                    dbWriter.WriteLine("<xs:extension base=\"xs:string\">");
                    dbWriter.WriteLine("<xs:attribute name=\"xlinkhref\" type=\"xs:string\" />");
                    dbWriter.WriteLine("<xs:attribute name=\"ext-link-type\" type=\"xs:string\" />");
                    dbWriter.WriteLine("</xs:extension>");
                    dbWriter.WriteLine("</xs:simpleContent>");
                    dbWriter.WriteLine("</xs:complexType>");
                    dbWriter.WriteLine("</xs:element>");
                    dbWriter.WriteLine("</xs:schema>");
                }
            }

        }
        private void BootStrapAppSettingsFile()
        {
            try
            {
                if (File.Exists(Path.Combine(AppDataDir, @"Ontology.xml")))
                {
                    DateTime dtOntologyFile = File.GetLastWriteTime(Path.Combine(AppDataDir, @"Ontology.xml"));
                    TimeSpan tsOntologyFile = DateTime.Now - dtOntologyFile;
                    if (tsOntologyFile.TotalDays > 1)
                        CreateXmlDocument();
                }
                else
                    CreateXmlDocument();
            }
            catch (Exception)
            {
            }
        }

        private void CreateXmlDocument()
        {
            try
            {
                string URL = string.Empty;
                if (File.Exists(Path.Combine(AppDataDir, @"BiolitSettings.xml")))
                    URL = Biolit_Settings.Settings.MainURL;
                else
                    URL = "http://rest.bioontology.org/bioportal/ontologies" + @"?apikey=bd750df3-3ec6-4383-b506-6ad887cfdcd1";
                _docNavigator = new XPathDocument(URL);
                _navigator = _docNavigator.CreateNavigator();
                XmlTextWriter _xmlTextWriter = new XmlTextWriter(Path.Combine(AppDataDir, @"Ontology.xml"), Encoding.Unicode);
                _xmlTextWriter.WriteStartDocument();
                _xmlTextWriter.WriteNode(_navigator, true);
                _xmlTextWriter.WriteEndDocument();
                _xmlTextWriter.Close();
                _nodeIterator = _navigator.Select("/success/data/list/ontologyBean[format='OBO']");
                List<OntList> ol = new List<OntList>();
                while (_nodeIterator.MoveNext())
                {

                    OntList ontologyList = new OntList();

                    if (null != _nodeIterator.Current.SelectSingleNode("displayLabel"))
                    {
                        ontologyList.Name = _nodeIterator.Current.SelectSingleNode("displayLabel").Value;
                    }
                    if (null != _nodeIterator.Current.SelectSingleNode("id"))
                    {
                        ontologyList.ID = _nodeIterator.Current.SelectSingleNode("id").Value;
                    }
                    if (null != _nodeIterator.Current.SelectSingleNode("versionNumber"))
                    {
                        ontologyList.Version = _nodeIterator.Current.SelectSingleNode("versionNumber").Value;
                    }
                    else
                    {
                        ontologyList.Version = "unknown";
                    }
                    if (null != _nodeIterator.Current.SelectSingleNode("format"))
                    {
                        ontologyList.Format = _nodeIterator.Current.SelectSingleNode("format").Value;
                    }
                    ontologyList.Source = "Rest WebServices";
                    if (false == String.IsNullOrEmpty(ontologyList.Name) && false == String.IsNullOrEmpty(ontologyList.ID)
                            && false == String.IsNullOrEmpty(ontologyList.Format))
                    {
                        if (false == AlreadyExists(ol, ontologyList))
                            ol.Add(ontologyList);
                    }
                };
                Biolit_Settings.Settings = new ConfigSettings();
                Biolit_Settings.Settings.AvailableOntologies = ol.ToArray();
                List<OntologyDownloadLocation> OntologyDownloadLoc = new List<OntologyDownloadLocation>();
                OntologyDownloadLoc.Add(new OntologyDownloadLocation("National Center for Biomedical Ontology", "http://rest.bioontology.org/bioportal/ontologies/download"));
                Biolit_Settings.Settings.AvailableDownloadURLs = OntologyDownloadLoc.ToArray();
                Biolit_Settings.Settings.MainURL = URL;
                Biolit_Settings.Settings.ontologiesUpdate = true;
                Biolit_Settings.Settings.downloadsSettings = 10;
                Biolit_Settings.Settings.OBO_DWNLDS = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Biolit_TechPreview_Dec_2009\Ontologies\");
                Biolit_Settings.Settings.SettingsVersion = 0;
                Biolit_Settings.Settings.InlineMatching = true;
                Biolit_Settings.StoreSettings();
            }
            catch (Exception)
            {
            
            }
        }

     private bool AlreadyExists(List<OntList> ontList, OntList addList)
        {
            Boolean alreadyInSelectedList = false;
            if (ontList != null && ontList.Count > 0)
            {
                foreach (OntList onlist in ontList)
                {
                    if (onlist.Name.Equals(addList.Name, StringComparison.CurrentCultureIgnoreCase))
                    {
                        alreadyInSelectedList = true;
                        break;
                    }
                }
            }
            return alreadyInSelectedList;
        }
    }
}
